define(function (require, exports, module) {
	'use strict';
	var Template,
		$ = require("lib/jquery/jquery"),
		OC = require("lib/core/oc");

	/**
	 * 模板的构造函数，管理模板不同阶段的缓存，激活状态
	 * 数据，模板原文，和渲染完毕的回调。
	 *
	 * @class Template
	 * @constructor
	 * @param response {string} 模板的原始原文
	 * @param [data] {object} 数据对象，可以在构造的时候初始化
	 * @param [callback] {function} 定义模板被渲染或重渲染之后做的事情
	 */
	Template = function Template(template_name, template_string, data, callback) {
		this.name = template_name;
		/**
		 * 模板的激活状态
		 *
		 * @property active
		 * @type boolean
		 */
		this.active = false;
		/**
		 * 模板的最初原文，作为ajax的response被第一次构建，这里用于缓存初始原文
		 * 使用jsRender框架
		 *
		 * @property response
		 * @type string
		 */
		this.view = $.templates(template_string);
		/**
		 * 模板的数据，有指定的格式，静态的模板可以在构造时初始化
		 * data在原型方法里有指定的输入方法
		 * data也是Template模型的缓存
		 *
		 * @property data
		 * @type object
		 */
		if (data) {
			this.data = data;
			this.data.lang = this.lang_packs[OC.cfg("CURRENT_LANG")];
		} else {
			this.data = this.noneData();
		}
		/**
		 * 模板在渲染和重渲染之后需要执行的用户自定义的函数内容，不会在构造阶段调用
		 * callback实际上是Template的控制器
		 *
		 * @property callback
		 * @type function
		 */
		if (typeof callback === "function") {
			this.callback = callback;
		} else {
			this.callback = this.noneCallback;
		}
		/**
		 * 计时器管理
		 *
		 * @property timers
		 * @type object
		 */
		this.timers = {
			timeout: [],
			interval: []
		};
	};
	/**
	 * 激活这个模板：清空旧的计时器；刷新激活标识；切换语言；渲染出innerHTML并追加到
	 * <body>；执行绑定的模板控制器回调函数。
	 * 注：在激活方法里执行清理计时器操作是为了refresh和open操作时都能正确触发。
	 *
	 * @param [data] {object} 待刷新的数据
	 * @chainable
	 */
	Template.prototype.activeMe = function (data) {
		var html, wrap = $("#tpl-" + this.name), tplElement ;
		// 清除旧的计时器
		this.clearAllTimer().setActive().switchLanguage();
		if (typeof data === "object") {
			this.setData(data);
		}
		
		html = this.view.render(this.data);
		if (wrap.length) {
			wrap.html(html);
			$("[tpl=" + this.name + "]").unwrap();
		} else {
			$("body").append(html);
		}
		tplElement = $("[tpl=" + this.name + "]").css("z-index", 100000).get(0);
		// 执行绑定的控制器回调
		this.callback.call(tplElement);

		return this;
	};
	/**
	 * 使当前模板自己失效
	 *
	 * @param [data] {object} 待刷新的数据
	 * @chainable
	 */
	Template.prototype.deactiveMe = function () {
		var name = this.name;
		$("[tpl=" + name + "]").wrap("<div id=\"tpl-" + name + "\" style=\"display:none;\"></div>").remove();
		this.setInactive().clearAllTimer();

		return this;
	};
	/**
	 * 刷新自己，说白了就是失效自己再激活
	 *
	 * @param [data] {object} 待刷新的数据
	 * @chainable
	 */
	Template.prototype.refreshMe = function (data) {
		this.deactiveMe().activeMe(data);
		
		return this;
	};
	/**
	 * 设置受模板管理的超时计时器
	 *
	 * @param time {number} 时间长度
	 * @param callback {function} 执行的过程
	 * @chainable
	 */
	Template.prototype.setTimeout = function (time, callback) {
		var id = setTimeout(callback, time);
		this.timers.timeout.push(id);

		return id;
	};
	/**
	 * 设置受模板管理的循环计时器
	 *
	 * @param time {number} 时间长度
	 * @param callback {function} 执行的过程
	 * @chainable
	 */
	Template.prototype.setInterval = function (time, callback) {
		var id = setInterval(callback, time);
		this.timers.interval.push(id);

		return id;
	};
	/**
	 * 清除本模板的所有计时器
	 *
	 * @param time {number} 时间长度
	 * @param callback {function} 执行的过程
	 * @chainable
	 */
	Template.prototype.clearAllTimer = function () {
		var i, len;
		len = this.timers.timeout.length;
		if (len > 0) {
			for (i = 0; i < len; i += 1) {
				clearTimeout(this.timers.timeout.pop());
			}
		}
		len = this.timers.interval.length;
		if (len > 0) {
			for (i = 0; i < len; i += 1) {
				clearInterval(this.timers.interval.pop());
			}
		}
		return this;
	};
	/**
	 * 语言包数据管理对象
	 *
	 * @property lang_packs
	 * @type object
	 */
	Template.prototype.lang_packs = {};
	/**
	 * 无data的时候指向该原型属性
	 *
	 * @method noneData
	 * @returns {object} 空对象
	 */
	Template.prototype.noneData = function () {
		return {};
	};
	/**
	 * 无callback的时候指向该原型
	 *
	 * @method noneCallback
	 * @returns {function} 空函数
	 */
	Template.prototype.noneCallback = function () {
		return;
	};
	Template.prototype.switchLanguage = function () {
		this.data.lang = this.lang_packs[OC.cfg("CURRENT_LANG")];

		return this;
	};
	/**
	 * 判断模板是不是激活状态
	 *
	 * @method isActive
	 * @returns {boolean} 激活为true，非激活为false
	 */
	Template.prototype.isActive = function () {
		return this.active === true;
	};
	/**
	 * 将该模板置于激活状态
	 *
	 * @method setActive
	 * @chainable
	 */
	Template.prototype.setActive = function () {
		this.active = true;
		return this;
	};
	/**
	 * 将该模板置于非激活状态
	 *
	 * @method setInactive
	 * @chainable
	 */
	Template.prototype.setInactive = function () {
		this.active = false;
		return this;
	};
	/**
	 * 将数据追加进模板的data中
	 *
	 * @method setData
	 * @param data {object} 需要被追加的数据
	 * @chainable
	 */
	Template.prototype.setData = function (data) {
		var data_key;
		for (data_key in data) {
			if (data.hasOwnProperty(data_key)) {
				this.data[data_key] = data[data_key];
			}
		}
		return this;
	};
	/**
	 * 从模板的data查询指定键值的数据
	 *
	 * @method getData
	 * @param key {string} 目标键值
	 * @returns {string|number|array|boolean} 对应的数据值
	 */
	Template.prototype.getData = function (key) {
		if (this.data.hasOwnProperty(key)){
			return this.data[key];
		}
		return false;
	};
	/**
	 * 将一个object直接替换模板的data
	 *
	 * @method fanIn
	 * @param data {object} 数据对象
	 * @chainable
	 */
	Template.prototype.fanIn = function (data) {
		this.data = data;
		return this;
	};
	/**
	 * 输出该模板的整个data
	 *
	 * @method fanOut
	 * @returns {object} 模板的数据对象
	 */
	Template.prototype.fanOut = function () {
		return this.data;
	};

	return Template;
});